﻿/*
 * Kinect Tilt Control v1.0
 * by Federico Del Bene, email: federico AT delbene DOT eu
 * released under license GPL v3
*/

using System;
using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.Kinect;

namespace KinectTiltControl
{
    public partial class Form1 : Form
    {

        // Configuration file name.
        string configFileName = "config.ini";

        // Parameters.
        int tiltAtApplicationStart = 0;
        int tiltAtApplicationStop = 0;

        // Array of sensor's movements.
        DateTime[] movements = new DateTime[15];
        // Index of array containing the time of last sensor's movement.
        int lastMovementIndex;
        // Last movement time: corresponds to a value in movement[].
        DateTime lastMovement;

        // Miminum interval between two movements.
        TimeSpan minimumInterval = new TimeSpan(0, 0, 1);
        // Miminum interval after 15 consecutive movements.
        TimeSpan extendedInterval = new TimeSpan(0, 0, 20);

        public Form1()
        {
            InitializeComponent();

            // Start minimized in the system tray.
            this.WindowState = FormWindowState.Minimized;
            this.ShowInTaskbar = false;

            // Read configuration file.
            List<string> configLines = new List<string>();
            try
            {
                configLines = new List<string>(File.ReadAllLines(configFileName));
            }
            catch (Exception)
            {
                // Continue, will use hard-wired parameters.
            }

            // Get parameters. If there are no lines, will skip and use hard-wired settings.
            foreach (string configLine in configLines)
            {
                if (configLine.Length != 0 && !configLine.StartsWith("#"))
                {
                    try
                    {
                        if (configLine.StartsWith("TiltAtApplicationStart="))
                        {
                            tiltAtApplicationStart = Int32.Parse(configLine.Substring(23));
                            if (tiltAtApplicationStart > +27)
                                tiltAtApplicationStart = +27;
                            if (tiltAtApplicationStart < -27)
                                tiltAtApplicationStart = -27;
                        }
                        if (configLine.StartsWith("TiltAtApplicationStop="))
                            tiltAtApplicationStop = Int32.Parse(configLine.Substring(22));
                        {
                            if (tiltAtApplicationStop > +27)
                                tiltAtApplicationStop = +27;
                            if (tiltAtApplicationStop < -27)
                                tiltAtApplicationStop = -27;
                        }
                    }
                    catch (Exception)
                    {
                        // Continue, will use hard-wired parameters.
                    }
                }
            }

            // Set the chosen tilt.
            try
            {
                // Create Kinect object (will acquire only the first Kinect in the system).
                KinectSensor sensor = KinectSensor.KinectSensors[0];

                // Access sensor.
                sensor.Start();

                // Set elevation angle to tiltAtApplicationStart.
                sensor.ElevationAngle = tiltAtApplicationStart;

                // Register movement in the array, at index 0.
                lastMovementIndex = 0;
                lastMovement = DateTime.UtcNow;
                movements[lastMovementIndex] = lastMovement;

                // Update the taskbar accordingly.
                trackBar1.Value = tiltAtApplicationStart;

                // Release the sensor, freeing it for other apps.
                sensor.Stop();
            }
            catch (Exception)
            {
                // Show message and close application.
                MessageBox.Show("There was a problem accessing the Kinect sensor. Cannot apply TiltAtApplicationStart.");
            }
        } 

        private void Form1_Resize(object sender, EventArgs e)
        {
            // Will hide the application when it's minimized, so that it won't appear on the task bar.
            if (FormWindowState.Minimized == WindowState)
                this.Hide();
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            // Application will be restored when the icon is double-clicked.
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            // When the application is closed, reduce it in the system tray.
            if (e.CloseReason == CloseReason.UserClosing)
            {
                notifyIcon1.Visible = true;
                this.Hide();
                e.Cancel = true;
            }
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            // Set the chosen tilt.
            try
            {
                // Create Kinect object (will acquire only the first Kinect in the system)
                KinectSensor sensor = KinectSensor.KinectSensors[0];

                // Access sensor.
                sensor.Start();

                //  Wait minimumInterval if necessary.
                if (DateTime.UtcNow.Subtract(lastMovement) < minimumInterval)
                    System.Threading.Thread.Sleep(1000);

                // Set elevation angle to tiltAtApplicationStop's value and register movement in the array, at index lastMovement + 1 (modulus 15, as array only contains last 15 movements),
                sensor.ElevationAngle = tiltAtApplicationStop;
                lastMovementIndex = (lastMovementIndex + 1) % 15;
                movements[lastMovementIndex] = DateTime.UtcNow;

                // Release the sensor, freeing it for other apps.
                sensor.Stop();

                // Exits the application.
                Application.Exit();
            }
            catch (Exception)
            {
                // Show message and close application.
                MessageBox.Show("There was a problem accessing the Kinect sensor. Cannot apply TiltAtApplicationStop.");
                Application.Exit();
            }
        }

        private void trackBar1_MouseUp(object sender, MouseEventArgs e)
        {
            // Set the chosen tilt.
            try
            {
                // Create Kinect object (will acquire only the first Kinect in the system)
                KinectSensor sensor = KinectSensor.KinectSensors[0];

                // Access sensor.
                sensor.Start();

                //  Wait minimumInterval if necessary.
                if (DateTime.UtcNow.Subtract(lastMovement) < minimumInterval)
                    System.Threading.Thread.Sleep(1000);

                // Set elevation angle to trackbar's value and register movement in the array, at index lastMovement + 1 (modulus 15, as array only contains last 15 movements),
                sensor.ElevationAngle = trackBar1.Value;
                lastMovementIndex = (lastMovementIndex + 1) % 15;
                movements[lastMovementIndex] = DateTime.UtcNow;

                // Release the sensor, freeing it for other apps.
                sensor.Stop();

                // If this the 15th consecutive movement, wait 20 seconds.
                if(lastMovementIndex == 14)
                {
                    trackBar1.Enabled = false;
                    System.Threading.Thread.Sleep(20000);
                    trackBar1.Enabled = true;
                }
            }
            catch (Exception)
            {
                // Show message and close application.
                MessageBox.Show("There was a problem accessing the Kinect sensor. Cannot apply selected tilt.");
            }
        }
    }
}
